/******************************************************************************
*  COPYRIGHT MorningCore CO.,LTD
******************************************************************************/

/*****************************************************************
* FileName::    <TxFilter.c>
* version::     <0.2.0>
* Purpose:      <Tx Filter>
* Authors:      <shanshan, 2010-06-24>
* Notes:        <no>
******************************************************************/

/******************************************************************************
*  HISTORY OF CHANGES
*   <Date>          <Author>        <Version>       <DESCRIPTION>
*   2009-10-09      shanshan         0.1.0           original
*   2009-11-18      zhangyanan       0.1.1           add double-point code
*   2010-06-22      shanshan         0.2.0           modified according to algorithm
******************************************************************************/

/******************************************************************************
*  INCLUDE FILES

******************************************************************************/

#include "ue_tx_prach_firfilter_fix.h"
/*****************************************************************************
* Function: Fir_Tx()
* Purpose:  This function designs an interpolation Filter.
*
* Relation:
                        Calls       : lib_arith_N.c
                        Called by   : SRP_Top.c
* Params:
*   <Name>          <Type>      <In/Out>    <Description>
*   Input[]          fractN       In          input data
*   InputLen         uint16       In          length of the input data
*   CoefTx[]         fractN       In          coefficients of the TxFilter
*   CoefTxLen        uint16       In          length of the coefficients
*   Output[]         fractN       Out         output data
* Return:  void
* Note:    <no>
*******************************************************************************/
void Fir_Tx_fix(
    int     N_up,         // Up Sampleing  factor
    fractN  Input[],
    uint32  InputLen,
    fractN  CoefTx[],
    uint16  CoefTxLen,
    fractN  Output[],
    int8    BitLength
)
{
    uint32   i;
    int      j;
    fract40  Sum_Filter;
    fractN   Ceof_N;
    fractM   x_n_2N, x_p_2N, sum_x_2N, Sum_Filter_2N, x_2N;
    static fractN  *x;

    x = (fractN *) malloc((N_up * InputLen + CoefTxLen) * sizeof(fractN));
    memset(x, 0, (N_up * InputLen + CoefTxLen)*sizeof(fractN));

    /* define a mid-variables for convolution */
    for (i = 0; i < InputLen; i++) //added by shanshan20100624
    {
        x[N_up * i + CoefTxLen / 2] = Input[i];
    }

    //////// added by jinxiaolong, 2012-06-07, CRID: Enh00000282 begin
    for (i = 0; i < (N_up * InputLen); i++)
    {
        Sum_Filter.accw32 = 0;
        Sum_Filter.accx8 = 0;

        Ceof_N   = CoefTx[CoefTxLen / 2];                   // Q(N,1)
        x_2N     = x[i + CoefTxLen / 2];
        x_2N     = Shl_fr1xM(x_2N, (int)(BitLength - 1));    // Q(M,2)
        sum_x_2N = Mlt_frNXfrM_frM(Ceof_N, x_2N);
        Add_frM_40(&Sum_Filter, sum_x_2N);

        for (j = 1; j <= CoefTxLen / 2; j++)
        {
            Ceof_N  = CoefTx[CoefTxLen / 2 - j];

            x_n_2N  = x[i + CoefTxLen / 2 - j];                    // Q ( N,1 )
            x_p_2N  = x[i + CoefTxLen / 2 + j];
            x_n_2N  = Shl_fr1xM(x_n_2N, (int)(BitLength - 1));
            x_p_2N  = Shl_fr1xM(x_p_2N, (int)(BitLength - 1));      // Q ( M,2 )
            sum_x_2N = Add_fr1xM(x_n_2N, x_p_2N);
            sum_x_2N = Mlt_frNXfrM_frM(Ceof_N, sum_x_2N);          // Q ( M,2 )
            Add_frM_40(&Sum_Filter, sum_x_2N);
        }
        Sum_Filter_2N = Fract40_to_fractM(Sum_Filter);             // Q ( M,2)
        Sum_Filter_2N = Shl_fr1xM(Sum_Filter_2N, 1);               // Q ( M,1)

        Output[i] = Round_fr1xM(Sum_Filter_2N);
    }
    //////// added by jinxiaolong, 2012-06-07, CRID: Enh00000282 end
    free(x);
}

void Fir_Tx_fix_Cmplx(
	int     N_up,         // Up Sampleing  factor
	cmplx_frN  Input[],
	uint32  InputLen,
	fractN  Coef[],
	uint16  CoefLen,
	cmplx_frN  Output[],
	int8    BitLength
)
{
	int j;
	fractN *InputRe, *InputIm; // input
	fractN *OutputRe, *OutputIm; // output

	Set_bit_width(BitLength);

	InputRe = (fractN *)malloc(sizeof(fractN) * InputLen);
	InputIm = (fractN *)malloc(sizeof(fractN) * InputLen);
	OutputRe = (fractN *)malloc(sizeof(fractN) * (InputLen * N_up));
	OutputIm = (fractN *)malloc(sizeof(fractN) * (InputLen * N_up));

	// read input
	for (j = 0; j < InputLen; j++)
	{
		InputRe[j] = Input[j].re;
		InputIm[j] = Input[j].im;
	}

	// real up
	Fir_Tx_fix
	(
		N_up,
		InputRe,
		InputLen,
		Coef,
		CoefLen,
		OutputRe,
		BitLength
	);
	// imag up
	Fir_Tx_fix
	(
		N_up,
		InputIm,
		InputLen,
		Coef,
		CoefLen,
		OutputIm,
		BitLength
	);

	// write output
	for (j = 0; j < N_up*InputLen; j++)
	{
		Output[j].re = OutputRe[j];
		Output[j].im = OutputIm[j];
	}

	free(InputRe);
	free(InputIm);
	free(OutputRe);
	free(OutputIm);
}
